﻿<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <!-- 因为 AJAX 库和通用工具的生态已经相当丰富，Vue 核心代码没有重复 -->
    <!-- 提供这些功能以保持精简。这也可以让你自由选择自己更熟悉的工具。 -->
    <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script>
</head>
<body>
    <!--Start Learn1 v:on:click="" v-bind:title=""
        v-if="" v-for="xx in xxx" v-model="" 组件 -->
    <div name="first">
        <!--文本插值-->
        <div id="app">
            {{ message }}
        </div>

        <!--绑定元素特性-->
        <div id="app-2">
            <span v-bind:title="message">
                鼠标悬停几秒钟查看此处动态绑定的提示信息！
            </span>
        </div>

        <!--条件-->
        <!--不仅可以把数据绑定到 DOM 文本或特性，还可以绑定到 DOM 结构-->
        <div id="app-3">
            <p v-if="seen">现在你看到我了</p>
        </div>

        <!--循环-->
        <!--todolist-->
        <div id="app-4">
            <ol>
                <li v-for="todo in todos">
                    {{todo.text}}
                </li>
            </ol>
        </div>

        <!--事件监听-->
        <div id="app-5">
            <p>{{message}}</p>
            <button v-on:click="joinAuthor">加上作者信息</button>
        </div>

        <!--v-model用户输入-->
        <div id="app-6">
            <p>{{message}}</p>
            <input v-model="message" />
        </div>

        <!--组件-->
        <div id="app-7">
            <ol>
                <!--v-bind:todo---关联props-->
                <todo-item v-for="item in breakfast"
                           v-bind:todo="item"
                           v-bind:key="item.id">

                </todo-item>
            </ol>
        </div>

    </div>

    <script>
        var app = new Vue({
            el: '#app',
            data: {
                message: 'Hello Vue!'
            }
        })

        var app2 = new Vue({
            el: '#app-2',
            data: {
                message: '页面加载于 ' + new Date().toLocaleString()
            }
        })

        var app3 = new Vue({
            el: "#app-3",
            data: {
                seen: true
            }
        })

        var app4 = new Vue({
            el: '#app-4',
            data: {
                todos: [
                    { text: '学习js' },
                    { text: '学习vue' },
                    { text: '还是学习ts吧' }
                ]
            }
        })

        app4.todos.push({ text: '新项目' })

        var app5 = new Vue({
            el: "#app-5",
            data: {
                message:"hello vue.js 我是萌新，对我好点"
            },
            methods: {
                joinAuthor: function () {
                    this.message = this.message+'\n Author:Randy'
                }
            }
        })

        var app6 = new Vue({
            el: '#app-6',
            data: {
                message:'我是萌新，尤大大'
            }
        })


        //声明一个组件
        Vue.component('todo-item', {
            //todo-item组件接受一个prop的自定义特性
            props: ['todo'],
            template:'<li>{{todo.text}}</li>'
        })

        var app7 = new Vue({
            el: "#app-7",
            data: {
                breakfast: [
                    { id: 0, text: '包子' },
                    { id: 1, text: '稀饭' },
                    { id: 2, text: '馒头' }
                ]
            }
        })
    </script>
    <!--End Learn1v:on:click="" v-bind:title=""
        v-if="" v-for="xx in xxx" v-model=""-->
    <!--Start Learn2 Object.freeze() vm.$watch('',function(){})-->
    <div name="second">
        <div id="app-8">
            <p>{{foo}}</p>
            <button v-on:click="foo='baz'">
                让我改变他的值
            </button>
        </div>

        <div id="example">

        </div>
    </div>

    <script type="text/javascript">
        //我们的数据对象
        var data = { a: 1 }

        //该对象被加入到一个Vue实例中
        var vm = new Vue({
            data: data
        })

        //获得这个实例上的属性
        //返回源数据中对应的字段
        console.log("vm.a与data.a的值是否相等？ture为是，false为不等：")
        console.log(vm.a == data.a)

        //设置属性也会影响到原始数据
        vm.a = 2
        console.log("设置vm.a=2,测试data.a=" + data.a)

        //设置原始数据
        data.a = 3
        console.log("设置data.a=3,测试vm.a=" + vm.a)

        //此例结论：数据改变，视图会进行重新渲染
        //【重点】只有当实例被创建时 data 中存在的属性才是响应式的。
        //后面加的vm.b的改动不会创建任何视图的更新，
        //后面研究原理, 暂时先死记硬背，当语法记

        //如果你知道你会在晚些时候需要一个属性，
        //但是一开始它为空或不存在，那么你仅需要设置一些初始值。

        var obj = {
            foo: 'bar'
        }

        //阻止修改现有的属性，也意味着响应系统无法再追踪变化
        //可注释 与 取消注释 进行界面测试
        //[Vue warn]: Error in v-on handler: "TypeError: "foo" is read-only"
        Object.freeze(obj)

        var app8 = new Vue({
            el: "#app-8",
            data: obj
        })


        //Vue 实例还暴露了一些有用的实例属性与方法。
        //它们都有前缀 $，以便与用户定义的属性区分开来。

        var data2 = { a: 1 }
        var vm = new Vue({
            el: '#example',
            data: data2
        })
        console.log("start----------")
        vm.$data === data2
        vm.$el === document.getElementById('example')

        //$watch 是一个实例方法--监视a的值
        vm.$watch('a', function () {
            //这个回调将在'vm.a'改变后调用
            console.log("a的值改变了，现在a为:" + vm.a);
        })
        console.log("end----------")
    </script>

    <!--End Learn2 Object.freeze() vm.$watch('',function(){})-->
    <!--End Learn3 生命周期-->
    <div name="3">


    </div>

    <script type="text/javascript">
        //Vue实例创建-设置数据监听-编译模板，实例挂载到DOM，数据变化-更新DOM
        //以上这些过程中就会运行一些生命周期钩子的函数，
        //就可以在这些生命周期添加自己的代码的机会
        /* created 钩子*/
        var abc = new Vue({
            data: {
                a: 1
            },
            created: function () {
                //'this'指向vm实例
                console.log('abc被创建了，现在正在执行created钩子，钩子函数里面执行代码是：a is:' + this.a)
            }
        })

        //【注意】【注意】

        /*  不要在选项属性或回调上使用箭头函数，
         *  比如
         *  created: () => console.log(this.a) 或
         *  vm.$watch('a', newValue => this.myMethod()) 。
         *  因为箭头函数并没有 this，
         *  this 会作为变量一直向上级词法作用域查找，
         *  直至找到位置，【经常导致】
         *  Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function
         *  之类的错误。*/
        //=>'a is: 1'

        /*mounted*/



        /*updated*/


        /*destroyed*/

        /*生命周期 示意图
          1.[Vue实例化]-new Vue()

          2.[初始化事件与生命周期开始]，之后,钩子-【beforeCreate】

          3.[初始化注入与响应]，之后，钩子-created

          4.判断是否有'el'选项

                有
                    判断是否有'template'选项

                无
                    when vm.$mount(el) is called-暂时不能理解
                     判断是否有'template'选项

           5. 4中判断

                有
                    原话:Compile template into render function
                    翻译:编译模板至渲染函数

                无
                    原话：Compile el's outerHTML as template *
                    翻译：把el中指定的id的HTML作为模板来编译
                ----总的可以归纳为[编译模板]

           6.5中完成，即进入生命周期钩子，

                换句话说，模板编译完成，之后，进入钩子-【beforeMount】


           7.[创建vm的$el(上面的测试已经说明$el等价document.getElementById())以及用创建好的替换el]，
                文档原话：Create vm.$el and replace "el" with it

                之后，进入钩子【mounted】

           8.[挂载]，挂载完成，剩下就是交互，交互过程中可能就会产生下面的内容

                当data发生变化，之后，进入钩子【beforeUpdate】

                [虚拟DOM重新渲染和patch(暂时找不到合适的翻译)]

                重新渲染和patch之后，进入钩子【updated】

           9.when vm.$destory() is called,调用实例销毁，

                进入钩子 - 【beforeDestory】

           10.Teardown watchers,child components and event listeners

                翻译：[拆卸或卸载，watchers-监视，子组件，事件监听]

           11.Destroyed,销毁完成

                即进入钩子-【destroyed】





         */

    </script>
    <!--End Learn3 生命周期-->
    <!-- Start Learn4 -->

    <script>
        /* Vue.js 使用了基于 HTML 的模板语法，
         * 允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。
         * 所有 Vue.js 的模板都是合法的 HTML ，
         * 所以能被遵循规范的浏览器和 HTML 解析器解析。

         在底层的实现上，Vue 将模板编译成虚拟 DOM 渲染函数。
         结合响应系统，Vue 能够智能地计算出最少需要重新渲染多少组件，
         并把 DOM 操作次数减到最少。

         如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量，
         你也可以不用模板，直接写渲染(render) 函数【好像在哪儿见过，想不起来】，
         使用可选的 JSX 语法。--【耐人寻味，因为不懂，所以耐人寻味】*/
    </script>

    <!-- End Learn4 -->
    <!-- Start Learn5 计算属性，侦听属性，侦听器watch-->

    <div>
        <div id="app-10">
            <!--Mustache语法-->
            <span v-once>Message:{{msg}}</span>
            <p>Using mustaches: {{ rawHtml }}</p>
            <p>Using v-html directive: <span v-html="rawHtml"></span></p>
        </div>

        <div id="app-11">
            <p>1+1={{sum}}</p>
            计算属性计算结果，请看下面:
            <p>1+1={{caculateSum}}</p>

            <p>{{single}}的平方是多少？</p>
            <p>天啦，经过复杂的计算，是{{squareValue}}</p>
        </div>

        <div id="app-13">
            <p>我的名:{{firstName}}</p>
            <p>我的姓:{{lastName}}</p>
            <p>所以我的全名{{fullName}}</p>
        </div>

        <div id="watch-example">
            <p>
                Ask a yes/no question,问一个是/否 问题:
                <input v-model="question">
            </p>
            <p>{{ answer }}</p>
        </div>
    </div>
    <script type="text/javascript">
        //[Vue warn]: Error in v - on handler: "TypeError: "foo" is read-only"
        //    (found in <Root>)
        var app10 = new Vue({
            el: '#app-10',
            data: {
                msg: "v-once测试",
                rawHtml: "<p>Using mustaches: </p>"
            }
        })
        /*
         * 【计算属性】
         * - 是基于它们的响应式依赖进行缓存的
         * 如果在计算属性中的方法像下面一样是计算出来的，
         * 但是不是像squareValue依赖single的值，就不是响应式的
         *
         * 所以记住一个新词【响应式依赖】
         */
        var app11 = new Vue({
            el: '#app-11',
            data: {
                sum: '?',
                single: '5'
            },
            computed: {
                caculateSum: function () {
                    return 1 + 1;
                },
                squareValue: function () {
                    return this.single * this.single;
                }
            }
        })

        /**
         *
         * 【侦听属性】-下面的例子可以改成【计算属性】
         *
         *
         * */
        var app12 = new Vue({
            el: '#app-12',
            data: {
                firstName: 'Randy',
                lastName: 'Field',
                fullName: 'RandyField'
            },
            watch: {
                firstName: function (val) {
                    this.fullName = val + ' ' + this.lastName
                },
                lastName: function (val) {
                    this.fullName = this.firstName + ' ' + val
                }
            }
        })

        var app13 = new Vue({
            el: '#app-13',
            data: {
                firstName: 'Randy',
                lastName: 'Field'
            },
            computed: {
                //fullName: function () {
                //    return this.firstName + ' ' + this.lastName
                //}


                fullName: {
                    // getter
                    get: function () {
                        return this.firstName + ' ' + this.lastName
                    },

                    // setter
                    set: function (newValue) {
                        var names = newValue.split(' ')
                        this.firstName = names[0]
                        this.lastName = names[names.length - 1]
                    }
                }

                //setter
            }
        })

        var watchExampleVM = new Vue({
            el: '#watch-example',
            data: {
                question: '',
                answer: 'I cannot give you an answer until you ask a question! 我不能给你答案，除非你有问题'
            },
            watch: {
                // 如果 `question` 发生改变，这个函数就会运行
                question: function (newQuestion, oldQuestion) {
                    this.answer = 'Waiting for you to stop typing...等待你的停止键入..'
                    this.debouncedGetAnswer()
                }
            },
            created: function () {
                // `_.debounce` 是一个通过 Lodash 限制操作频率的函数。
                // 在这个例子中，我们希望限制访问 yesno.wtf/api 的频率
                // AJAX 请求直到用户输入完毕才会发出。想要了解更多关于
                // `_.debounce` 函数 (及其近亲 `_.throttle`) 的知识，
                // 请参考：https://lodash.com/docs#debounce
                this.debouncedGetAnswer = _.debounce(this.getAnswer, 500)
            },
            methods: {
                getAnswer: function () {
                    if (this.question.indexOf('?') === -1) {
                        this.answer = 'Questions usually contain a question mark.键入的问题需要包括一个问号 ;-)'
                        return
                    }
                    this.answer = 'Thinking...，思考中...'
                    var vm = this
                    axios.get('https://yesno.wtf/api')
                        .then(function (response) {
                            vm.answer = _.capitalize(response.data.answer)
                        })
                        .catch(function (error) {
                            vm.answer = 'Error! Could not reach the API. ' + error
                        })
                }
            }
        })


        //迄今为止，在我们的模板中，我们一直都只绑定简单的属性键值。但实际上，对于所有的数据绑定，Vue.js 都提供了完全的 JavaScript 表达式支持。

        //{ { number + 1 } }
        //{ { ok ? 'YES' : 'NO' } }
        //{ { message.split('').reverse().join('') } }
        //<div v-bind: id="'list-' + id"></div>

        /* 1.v-if-条件
         *
         *         <p v-if="seen">现在你看到我了</p>
         *
         *          v-if 指令将根据表达式 seen 的值的真假来插入/移除 <p> 元素。
         *
         * 2.v-for-循环
         *
         * 3.v-bind-绑定值-响应式更新html特性<a v-bind:href="url">...</a>
         *
         * 4.v-on-监听
         *          <a v-on:click="doSomething">...</a>用于监听 DOM 事件
         *          在这里参数是监听的事件名
         *
         * 5.【Tip】方括号括起来的 JavaScript 表达式作为一个指令的参数：
         *
         *     <a v-bind:[attributeName]="url"> ... </a>
         *
         *      如果你的 Vue 实例有一个 data 属性 attributeName，其值为 "href"，那么这个绑定将等价于 v-bind:href
         *
         *      <a v-on:[eventName]="doSomething"> ... </a>
         *
         *      当 eventName 的值为 "focus" 时，v-on:[eventName] 将等价于 v-on:focus。
         *
         * 6.  .prevent 修饰符告诉 v-on 指令对于触发的事件调用 event.preventDefault()：
         *
         *     <form v-on:submit.prevent="onSubmit">...</form>
         *
         * 7. v-bind, v-on提供缩写，v-bind提供冒号【:】,v-on提供艾特号【@】
         *
         *      <!-- 完整语法 -->
         *      <a v-bind:href="url">...</a>
         *
         *      <!-- 缩写 -->
         *      <a :href="url">...</a>
         *
         *      <!-- 完整语法 -->
         *      <a v-on:click="doSomething">...</a>
         *
         *      <!-- 缩写 -->
         *      <a @click="doSomething">...</a>


         */
    </script>

    <!-- End Learn5 计算属性，侦听属性，侦听器watch-->
    <!-- Start Learn6 Class Style -->

    <div>
        <div id="app-14"
             class="static"
             v-bind:class="{active:isActive,'text-danger':hasError}">
            快审查元素，看看class吧-v-bind:class="{active:isActive,'text-danger':hasError}
        </div>
        <div id="app-15"
             class="static"
             v-bind:class="classObject">
            快审查元素，看看class吧-v-bind:class="classObject"
        </div>

        <div id="app-16"
             class="static"
             v-bind:class="[activeClass,errorClass]">
            快审查元素，看看class吧-v-bind:class="[activeClass,errorClass]"
        </div>

        <div id="app-17"
             class="static"
             v-bind:style="styleObject">
            快审查元素，看看style吧
        </div>
    </div>

    <script>
        var app14 = new Vue({
            el: '#app-14',
            data: {
                isActive: true,
                hasError: false
            }
        })

        var app15 = new Vue({
            el: '#app-15',
            data: {
                classObject: {
                    active: true,
                    'text-danger': true
                }
                //举一反三classObject可以去computed计算
            }
        })

        var app16 = new Vue({
            el: '#app-16',
            data: {
                activeClass: 'active',
                errorClass: 'text-danger'
            }
        })

        //同样的，对象语法常常结合返回对象的计算属性使用。
        var app17 = new Vue({
            el: '#app-17',
            data: {
                styleObject: {
                    color: 'red',
                    fontSize: '13px'
                }
            }
        })


        /* 【自动添加前缀】
         * 当 v-bind:style 使用需要添加浏览器引擎前缀的 CSS 属性时，
         * 如 transform，Vue.js 会自动侦测并添加相应的前缀
         *
         * 从 2.3.0 起你可以为 style 绑定中的属性提供一个包含多个值的数组，
         * 常用于提供多个带前缀的值，例如：
         * <div :style="{ display: ['-webkit-box', '-ms-flexbox', 'flex'] }"></div>
         * 这样写只会渲染数组中最后一个被浏览器支持的值。
         * 在本例中，如果浏览器支持不带浏览器前缀的 flexbox，
         * 那么就只会渲染 display: flex。
         */
    </script>

    <!-- End Learn6 -->
    <!-- Start Learn7 条件渲染-好东西  -->
    <div>
        <div id="app-18">
            <div v-if="Math.random() > 0.5">
                Now you see me
            </div>
            <div v-else>
                Now you don't
            </div>

            <div name="test" v-if="Math.random() > 0.5">
                现在你看见我了，我在v-if里面
            </div>
            <div v-else>
                你如果看到了，你肯定看不到v-if，因为我在v-else里面
            </div>
        </div>

        <div id="app-19">
            <template v-if="loginType === 'username'">
                <label>Username</label>
                <input name="username" placeholder="Enter your username">
            </template>
            <template v-else>
                <label>Email</label>
                <input name="email" placeholder="Enter your email address">
            </template>
            <input placeholder="输入你的密码" type="password">
            <button name="submit">{{btnLoginValue}}</button>
            <button v-on:click="changeLoginType">{{btnToggleValue}}</button>
        </div>
    </div>
    <!--<div v-if="type === 'A'">
        A
    </div>
    <div v-else-if="type === 'B'">
        B
    </div>
    <div v-else-if="type === 'C'">
        C
    </div>
    <div v-else>
        Not A/B/C
    </div>-->
    <script>
        var app18 = new Vue({
            el: '#app-18'
        })

        var app19 = new Vue({
            el: '#app-19',
            data: {
                loginType: 'username',
                btnLoginValue: '登录',
                btnToggleValue: '切换登录方式，现在为用户名登录,切换后就是邮箱了'
            },
            methods: {
                changeLoginType: function () {
                    if (this.loginType == 'username') {
                        this.btnToggleValue = '切换登录方式，现在为邮箱登录，切换后就是用户名了'
                        this.loginType = 'email'
                    }
                    else {
                        this.btnToggleValue = '切换登录方式，现在为用户名登录，切换后就是邮箱了'
                        this.loginType = 'username'
                    }
                }
            }
        })
        /*
         * v-if 是“真正”的条件渲染，
         *
         * 因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。
         *
         * v-if 也是惰性的：如果在初始渲染时条件为假，则什么也不做——直到条件第一次变为真时，才会开始渲染条件块。
         *
         * 相比之下，v-show 就简单得多——不管初始条件是什么，元素总是会被渲染，并且只是简单地基于 CSS 进行切换。
         *
         * 一般来说，v-if 有更高的切换开销，而 v-show 有更高的初始渲染开销。
         *
         * 因此，如果需要非常频繁地切换，则使用 v-show 较好；
         *
         * 如果在运行时条件很少改变，则使用 v-if 较好。
         *
         *
         * 【v-for v-if】当 v-if 与 v-for 一起使用时，v-for 具有比 v-if 更高的优先级,且尤雨溪
         *
         * 不推荐https://cn.vuejs.org/v2/guide/list.html#v-for-with-v-if
         * 可以查阅【风格指南】【列表渲染指南】
         *
         * */
    </script>
    <!-- End Learn7 条件渲染-好东西-->
    <!-- Start Learn8 列表渲染-好东西  -->
    <div>
        <div id="app-20">
            <ul>
                <!--<li v-for="item in apiLists">
                    {{prefix}}-{{item.api}}
                </li>-->
                <li v-for="(item,index) in apiLists">
                    {{index+1}}-{{prefix}}{{item.api}}
                </li>
            </ul>
        </div>

        <div id="app-21">
            <!--item in items-->
            <span v-for="value in apiLists">
                {{value}}
            </span>

            <!--(item,key) in items-->
            <p>下面是循环遍历的key与value</p>
            <div v-for="(value, key) in apiLists">
                {{ key }}: {{ value }}
            </div>
            <!--(item,key,index) in items-->
            <div v-for="(value, key, index) in apiLists" :key="value.id">
                {{ index }}. {{ key }}: {{ value }}
            </div>
        </div>
    </div>
    <script type="text/javascript">

        //数组遍历
        var app20 = new Vue({
            el: '#app-20',
            data: {
                prefix: 'api/zplus/ss/v1/Auth/',
                apiLists: [
                    { api: 'getAccessToken' },
                    { api: 'AuthTest' }
                ]
            }
        })

        //对象遍历

        var app21 = new Vue({
            el: '#app-21',
            data: {
                apiLists: {
                    prefix: 'api/zplus/ss/',
                    version: 'v1/',
                    route: 'auth/getaccess_token'

                }
            }
        })

    </script>

    <!--【重点】在遍历对象时，是按 Object.keys() 的结果遍历，
        但是不能保证它的结果在不同的 JavaScript 引擎下是一致的。-->
    <!--当 Vue.js 用 v-for 正在更新已渲染过的元素列表时，它默认用“【就地复用】”策略。
        如果数据项的顺序被改变，Vue 将不会移动 DOM 元素来匹配数据项的顺序，
        而是简单复用此处每个元素，
        并且确保它在特定索引下显示已被渲染过的每个元素。-->
    <!--这个默认的模式是高效的，
        但是只适用于不依赖子组件状态或临时 DOM 状态 (例如：表单输入值) 的列表渲染输出。-->
    <!-- End Learn8 列表渲染-好东西  -->







</body>
</html>